using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

using Rhino.Security.Interfaces;
using Rhino.Commons;
using DomainModel.Abstract;
using DomainModel.Entities;
using Rhino.Security.Model;

namespace WebUI.Controllers
{
    public class PermissionController : Controller
    {

        private readonly IAuthorizationRepository _authRepos;
        private readonly IPermissionsBuilderService _permissionsBuilderService;
        private readonly IPermissionsService _permissionService;
        private readonly IAuthorizationService _authorizationService;
        private readonly IUserRepository _userRepository;
        private readonly IProductsRepository _productsRepository;


        public PermissionController(
            IAuthorizationRepository authRepos,
            IPermissionsBuilderService permissionBuilderService,
            IPermissionsService permissionsService,
            IAuthorizationService authService,
            IUserRepository userRepository)
        {
            this._authRepos = authRepos;
            this._permissionsBuilderService = permissionBuilderService;
            this._permissionService = permissionsService;
            this._authorizationService = authService;
            this._userRepository = userRepository;
        }

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Administration()
        {
            
            if (HttpContext.Request.RequestType == "GET")
            {
                Models.Forms.PermissionsForm permForm = new Models.Forms.PermissionsForm();
                return View(permForm);
            }
            else
            {
                var opHomeIndex = HttpContext.Request["OpHomeIndex"];
                var opProductsList = HttpContext.Request["OpProductsList"];
                using (UnitOfWork.Start())
                {
                    var guest = _userRepository.GetUser("guest");
                    if (opHomeIndex == "Allow" && !_authorizationService.IsAllowed(guest, "/Home/Index"))
                    {
                        _permissionsBuilderService
                            .Allow("/Home")
                            .For("GuestGroup")
                            .OnEverything()
                            .DefaultLevel()
                            .Save();
                        UnitOfWork.Current.TransactionalFlush();
                    }
                    else if(opHomeIndex == "Deny" && _authorizationService.IsAllowed(guest, "/Home/Index"))
                    {
                        Permission[] perms = _permissionService.GetPermissionsFor(guest);
                        foreach (Permission tmp in perms)
                        {
                            if (tmp.Operation.Name == "/Home")
                                _authRepos.RemovePermission(tmp);
                        }
                        UnitOfWork.Current.TransactionalFlush();
                    }
                    if (opProductsList == "Allow" && !_authorizationService.IsAllowed(guest,"/Products/List"))
                    {
                        _permissionsBuilderService
                            .Allow("/Products")
                            .For("GuestGroup")
                            .OnEverything()
                            .DefaultLevel()
                            .Save();
                        UnitOfWork.Current.TransactionalFlush();
                    }
                    else if(opProductsList =="Deny" && _authorizationService.IsAllowed(guest,"/Products/List"))
                    {
                        Permission[] perms = _permissionService.GetPermissionsFor(guest);
                        foreach (Permission tmp in perms)
                        {
                            if (tmp.Operation.Name == "/Products")
                                _authRepos.RemovePermission(tmp);
                        }
                        UnitOfWork.Current.TransactionalFlush();
                    }
                }
                Models.Forms.PermissionsForm permForm = new Models.Forms.PermissionsForm();
                return View(permForm);
            }
        }

        public ActionResult Generate()
        {
            using (UnitOfWork.Start())
            {
                var hfranco = new User { UserName = ("hfranco"), Password = ("hfranco") };
                var guest = new User { UserName = ("guest"), Password = ("guest") };
                _userRepository.AddUser(hfranco);
                _userRepository.AddUser(guest);
                UnitOfWork.Current.TransactionalFlush();


                //Creating groups
                var AdminUserGroup = _authRepos.CreateUsersGroup("AdminGroup");
                UnitOfWork.Current.TransactionalFlush();
                var GuestUserGroup = _authRepos.CreateUsersGroup("GuestGroup");
                UnitOfWork.Current.TransactionalFlush();

                //Creating operations
                _authRepos.CreateOperation("/Products/List");
                UnitOfWork.Current.TransactionalFlush();
                _authRepos.CreateOperation("/Home/Index");
                UnitOfWork.Current.TransactionalFlush();

                //Assign users to group
                _authRepos.AssociateUserWith(hfranco, AdminUserGroup);
                _authRepos.AssociateUserWith(guest, GuestUserGroup);
                UnitOfWork.Current.TransactionalFlush();

                //Assigning operations to groups
                _permissionsBuilderService
                    .Allow("/Products")
                    .For("AdminGroup")
                    .OnEverything()
                    .DefaultLevel()
                    .Save();
                UnitOfWork.Current.TransactionalFlush();

                _permissionsBuilderService
                    .Allow("/Home")
                    .For("AdminGroup")
                    .OnEverything()
                    .DefaultLevel()
                    .Save();
                UnitOfWork.Current.TransactionalFlush();

                _permissionsBuilderService
                    .Allow("/Home")
                    .For("GuestGroup")
                    .OnEverything()
                    .DefaultLevel()
                    .Save();
                UnitOfWork.Current.TransactionalFlush();

                //Before deniying the view permission to the user.
                bool isAllowedProductsListOp = _authorizationService.IsAllowed(hfranco, "/Products/List");
                bool isAllowedProductsOp = _authorizationService.IsAllowed(hfranco, "/Products");

                bool isAllowedHomeOp = _authorizationService.IsAllowed(hfranco, "/Home");
                bool isAllowedHomeIndexOp = _authorizationService.IsAllowed(hfranco, "/Home/Index");

                bool isAllowedHomeGuestOp = _authorizationService.IsAllowed(guest, "/Home");
                bool isAllowedProductsGuestOp = _authorizationService.IsAllowed(guest, "/Products");

                //_permissionsBuilderService
                //    .Deny("/Products/Manage")
                //    .For(hfranco)
                //    .OnEverything()
                //    .Level(5)
                //    .Save();
                //UnitOfWork.Current.TransactionalFlush();


                //bool isAllowedProductManageOp = _authorizationService.IsAllowed(hfranco, "/Products/Manage");
                //bool isAllowedContentViewOp = _authorizationService.IsAllowed(hfranco, "/Products/View");

            }
            return null;
        }

        public ActionResult Remove()
        {
            using (UnitOfWork.Start())
            {
                var hfranco = _userRepository.GetUser("hfranco");
                var guest = _userRepository.GetUser("guest");
                //removing operations
                _authRepos.RemoveOperation("/Products/List");
                _authRepos.RemoveOperation("/Products");
                _authRepos.RemoveOperation("/Home/Index");
                _authRepos.RemoveOperation("/Home");
                UnitOfWork.Current.TransactionalFlush();

                //Removing child group
                _authRepos.RemoveUsersGroup("GuestGroup");
                _authRepos.RemoveUsersGroup("AdminGroup");
                UnitOfWork.Current.TransactionalFlush();

                //removing user from authorization table
                _authRepos.RemoveUser(hfranco);
                _authRepos.RemoveUser(guest);
                UnitOfWork.Current.TransactionalFlush();

                //Removing user from user table
                _userRepository.DeleteUser(hfranco);
                _userRepository.DeleteUser(guest);
                UnitOfWork.Current.TransactionalFlush();

            }

            return null;
        }

    }
}
